#include <string>
#include <typeindex>

namespace giant
{
	template<class T>
	class RuntimeClass
	{
	public:
		RuntimeClass()
		{
			++m_nRefCount;
		}

		RuntimeClass(const RuntimeClass<T>& org)
		{
			++m_nRefCount;
		}

		~RuntimeClass()
		{
			--m_nRefCount;
		}
		static size_t class_hash_code() {return m_type_index_hash_code;}
		static const std::string& class_name() {return m_type_index_name;}
		static bool test_class(size_t code) {return m_type_index_hash_code == code;}

		static long getRefCount() {return m_nRefCount;}
	private:
		static long	m_nRefCount;
		static size_t m_type_index_hash_code;
		static std::string m_type_index_name;
	};

	template<class T>
	long RuntimeClass<T>::m_nRefCount = 0;
	template<class T>
	size_t RuntimeClass<T>::m_type_index_hash_code = std::type_index(typeid(T)).hash_code();
	template<class T>
	std::string RuntimeClass<T>::m_type_index_name = std::type_index(typeid(T)).name();

	template<typename T,typename From>
	T* cast(From* from)
	{
		if (from && from->testClass<T>())
		{
			return (T*)(from);
		}
		return nullptr;
	}

	template<typename T>
	void logRefCount()
	{
		auto n = giant::RuntimeClass<T>::getRefCount();
		if(n)
		{
			Logger::allways("%32s:	%d",giant::RuntimeClass<T>::class_name().c_str(),n);
		}
	}
}

#define DEFINE_RUNTIME_BASECLASS(T) protected:\
	virtual bool testClass_impl(size_t class_code,bool recursive) const\
	{ return (class_code == giant::RuntimeClass<T>::class_hash_code()); }\
	virtual bool testClassName_impl(const std::string& name,bool recursive) const\
	{ return (name == giant::RuntimeClass<T>::class_name()); }\
	public:\
	template<typename T>\
	bool testClass(bool recursive = true) const\
	{\
		return testClass_impl(giant::RuntimeClass<T>::class_hash_code(),recursive);\
	}\
	bool testClassName(const std::string& name,bool recursive = true) const\
	{\
		return testClassName_impl(name,recursive);\
	}\

#define DEFINE_RUNTIME_CLASS(T) protected:\
	bool testClass_impl(size_t class_code,bool recursive) const override\
	{ if (class_code==giant::RuntimeClass<T>::class_hash_code()) return true; return recursive ? __super::testClass_impl(class_code,recursive) : false; }\
	bool testClassName_impl(const std::string& name,bool recursive) const override\
	{ if (name==giant::RuntimeClass<T>::class_name()) return true; return recursive ? __super::testClassName_impl(name,recursive) : false; }


